Øvelse 12

Opgave 1 - Processes

Exercise 1.1 - Simple process creation
int main()
{
  pid_t pid;
  pid = fork();
  if(pid == 0)
  {
    cout<<"Hi i am the child process! fork Value: " << pid << " pid value: " << getpid() << endl;
    //Child thing
    _exit(2);
  }
  else
  {
    cout<<"Hi i am the parent fork Value: " << pid << " pid value: " << getpid() << endl;
    wait(NULL);
    //Parent
  }
}
Output
Hi i am the parent fork Value: 22169 pid value: 22168
Hi i am the child process! fork Value: 0 pid value: 22169
 
Explain the value of PIDs and the return values from fork() - how can one finction return two different values?
fork() returnere som alle andre funktioner en enkelt værdi. Det som der sker med er fork er at den retunere i to processer hvor retur værdierne er forskellige.
Når vi er i child retunere fork() 0 og når den er i parrent retunere den childs PID.

Explain:
  • What happens to the memory from the parrent passed to the child?:
    • Child er en kopi af parrent og derfor deler de memory. Dette sker da fork() benytter Copy on write (COW) princippet.
  • what is passed to th childprocess and what is not?:
    • De fleste ting er passed undtagen følgende;
    • *  The child has its own unique process ID, and this PID does not match the ID of any existing process group  *  The child's parent process ID is the same as the parent's process ID.
      *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).
      *  Process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child.
      *  The child's set of pending signals is initially empty (sigpending(2)).
      *  The child does not inherit semaphore adjustments from its parent (semop(2)).
      *  The child does not inherit record locks from its parent (fcntl(2)).
      *  The child does not inherit timers from its parent (setitimer(2), alarm(2), timer_create(2)).
      *  The child does not inherit outstanding asynchronous I/O operations from its
         parent (aio_read(3), aio_write(3)), nor does it inherit any asynchronous
         I/O contexts from its parent (see io_setup(2)).


  • Why must it be _exit() that is called from within the child and not exit()?:
    • exit() laver cleanups(user-libs) ved at kalde cleanup funktionerne hvor _exit() kalder kun exit syscall for en process cleanup

Del 1.2 - Singe program - multiple process
int main()
{
  pid_t pid_1, pid_2;
  pid_1 = fork();
 
  int tick = 0;
  int tock = 0;
 
  if(pid_1 == -1)
  {
    cout<<"Something is wrong"<<endl;
    exit(EXIT_FAILURE);
  }
 
  else if (pid_1 == 0)
  {
    while (tick < 5)
    {
      cout<<"tick"<<tick<<endl;
      sleep(1);
      tick++;
    }
    _exit(0);
  }
 
  else if(pid_1 !=0)
  {
 
    pid_2 = fork();
    if(pid_2 == 0)
    {
      while(tock < 8)
      {
    cout<<"tock"<<tock<<endl;
    sleep(1);
    tock++;
      }
      _exit(0);
    }
    else if(pid_2 != 0)
    {
      wait(&pid_1);
      wait(&pid_2);
      cout<<"Done"<<endl;
      exit(0);
    }
  }
  return 0;
}
Output
stud@GoldenImage:~/Dropbox/3_semester/ISU/Ovelser/Exercise_12/del1.2$ ./testtock0
tick0
tock1
tick1
tock2
tick2
tock3
tick3
tock4
tick4
tock5
tock6
tock7
Done
 
snapshot4.png
Explain what happens when a process is spawned via the exec() function familiiy:
  • What is passed to the "child" process and what is not?
    • Det eneste som der er fælles for child og parent efter exec() er FILDESCRIPTORS
  • What should one be vary about when spawning processes in a security centext (in relation to the previous question)?
    • Hvis ikke child skal have adgang til filedescriptors skal have adgang til dem,
    • Som alternativ kan der benyttes closed_onexec.

Øvelse 2 - Shared Memory
memory.png






















  • Describe the concept behind shared memory, this includes which steps to go through and what to remember from a purely functional point of view:
      • shared memory betyder som navnet antyder at man dele memory. Dette sker imellem to eller flere processer.
      • Når man ønsker at gøre brug af shared memory skal man først allokere dette(bede om det og mappe det til ens adressserum). Når man er færdig med det shared memory skal man fjerne den fra ens adresserum og shared memory skal fjernes.
  • Under which circumstances would you consider shared memory a viable solution?:
      • Hvis man stille store krav til hastighed.
      • Om størrelsen på den data der skal deles vil blive for stor(primært applikationer med tung data som skal deles).
  • consider a scenario where two programs communicate via shared memory and program B has taken a mutex that program also waits for. In this unfortunate moment program B crash whilst having acquired said mutex
    • - What is the problem?:
      • Progammet vil stalled da A aldrig vil komme til. Låsen bliver ikke sluppet igen, derfor kan A intet gøre
    • - How would you resolve it?(google):
    • **
code
    • If the process containing the owning thread of a robust mutex terminates while holding the mutex lock, the next thread that acquires the mutex shall be notified about the termination by the return value [EOWNERDEAD] from the locking function. If the owning thread of a robust mutex terminates while holding the mutex lock, the next thread that acquires the mutex may be notified about the termination by the return value [EOWNERDEAD]. The notified thread can then attempt to mark the state protected by the mutex as consistent again by a call to pthread_mutex_consistent(). After a subsequent successful call to pthread_mutex_unlock(), the mutex lock shall be released and can be used normally by other threads. If the mutex is unlocked without a call to pthread_mutex_consistent(), it shall be in a permanently unusable state and all attempts to lock the mutex shall fail with the error [ENOTRECOVERABLE]. The only permissible operation on such a mutex is pthread_mutex_destroy().
    • code

- But using said approach what does this mean for what I may do in the critical section part, namely for the part where I have acquired the mutex?: